/**
 *  @file XmlWriter.h
 */
#ifndef _XMLWRITER_H_
#define _XMLWRITER_H_

#include "../../common/BaseObject.h"
#include "../../io/Writer.h"
#include "../../text/CFString.h"
#include "../../collections/ArrayT.h"
#include "../../collections/StackT.h"
#include "../../collections/HashtableT.h"
#include "../../lang/Primitive.h"
#include "../../util/BitAttributeT.h"
#include "XmlWriterSettings.h"

namespace cppflib
{

namespace xml
{

namespace writer
{

/**
 *  A class to write XML document
 */
class _DLLAPI XmlWriter : public BaseObject
{
private:
    xmlwritersettings_t writerSettings;
    util::BitAttributeT<enumforward_t> *pWriterState;
    collections::StackCppObjT<CFString> *pTagNameStack;
    collections::HashtableT<CFString, lang::Boolean> *pAttrTempTable; // to check duplicated attributes
    collections::HashtableT<lang::WChar, CFString> *pTempEscapedChars; // to store escaped characters
    io::Writer *pOutputWriter;
    
private:
    XmlWriter(void);
    void InternalInit(io::Writer * pOutputWriter);
    void WriteXmlDeclarationLine();
    void WriteNewline();
    void WriteIndentSpaces(bool isEndElement = false);
    void WriteClosingStartElement();
    void WriteStringValue(pcwstr_t str, int offset, int count);
    void WriteWhitespaces(u32_t numWS);

public:
	explicit XmlWriter(io::Writer * pOutputWriter);
    XmlWriter(io::Writer * pOutputWriter, xmlwritersettings_t &writerSettings);
	virtual ~XmlWriter(void);

    void Close();
    void Flush();

    XmlWriter & WriteStartElement(const CFString &localName);
    XmlWriter & WriteAttribute(const CFString &attrName, const CFString &attrValue);
    XmlWriter & WriteElementContent(const CFString &content);
    XmlWriter & WriteElementContent(const CFString &content, int offset, int count);
    XmlWriter & WriteElementContent(collections::ArrayWChar &content);
    XmlWriter & WriteElementContent(collections::ArrayWChar &content, int offset, int count);
    XmlWriter & WriteEndElement();
    XmlWriter & WriteFullEndElement();
    XmlWriter & WriteElement(const CFString &localName, const CFString &content);

    XmlWriter & WriteBase64(collections::ArrayByte &buffer, int offset, int count);
    XmlWriter & WriteCDATA(const CFString &text);
    XmlWriter & WriteComment(const CFString &comment);

    void WriteEndDocument();
    
    PUBLIC xmlwritersettings_t GetDefaultXmlWriterSettings();
};

} // end of namespace writer

} // end of namespace xml

} // end of namespace cppflib


#endif
